package com.prs.crm.service.project.impl;

import java.io.File;
import java.util.Collection;

import org.courser.Util;
import org.courser.ui.PaginationSupport;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;

import com.prs.crm.context.Constrains;
import com.prs.crm.context.FileUtil;
import com.prs.crm.context.ToolKits;
import com.prs.crm.dao.project.TaskDao;
import com.prs.crm.domain.hr.Person;
import com.prs.crm.domain.oa.Notice;
import com.prs.crm.domain.project.Project;
import com.prs.crm.domain.project.Task;
import com.prs.crm.domain.project.TaskAttach;
import com.prs.crm.exception.InValidException;
import com.prs.crm.service.hr.PersonService;
import com.prs.crm.service.impl.SimpleFlowServiceImpl;
import com.prs.crm.service.oa.NoticeService;
import com.prs.crm.service.project.ProjectService;
import com.prs.crm.service.project.TaskService;

public class TaskServiceImpl extends SimpleFlowServiceImpl<Task,TaskDao> implements TaskService{
	
	@Autowired
	private PersonService personService;
	
	@Autowired
	private ProjectService projectService;
	
	@Autowired
	private NoticeService noticeService;
	
	public void setProjectService(ProjectService projectService) {
		this.projectService = projectService;
	}

	public ProjectService getProjectService() {
		return projectService;
	}

	public void setNoticeService(NoticeService noticeService) {
		this.noticeService = noticeService;
	}

	public NoticeService getNoticeService() {
		return noticeService;
	}

	public void setPersonService(PersonService personService) {
		this.personService = personService;
	}

	public PersonService getPersonService() {
		return personService;
	}

	@Override
	public void save(Task task)
	{
		if (task.getParent()==null)
		{
			this.getProjectService().save(task.getProject());
		}
		if (task.getLocked() )
			throw new InValidException("任务已被锁定,不能点评");
		if (task.getId()!=null
				&& task.getRate()>0 && task.getRealStartTime()==null)
			task.setRealStartTime(Util.nowFullTime());
		if (task.getId()!=null
				&& task.getRate()!=null  && task.getRate()==100)
		{
			if (task.getChildTasks()!=null
					&& task.getChildTasks().size()>0)
			{
				for (Task childTask : task.getChildTasks())
				{
					if (childTask.getStatus()==null ||
							childTask.getStatus()!=Constrains.TASK_STATUS_END)
						throw new InValidException("有未完成的子任务或则子任务尚未审核,进度不能为100%");
					
				}
			}
		}
		super.save(task);
	}

	public void submitTask(Task task,File[] files,String[] fileNames)
	{
		task.addAllResults(FileUtil.getInstance().createAttach(files, fileNames));
		this.startFlow(task);
		sendVerifyNotice(task);
	}
	
	public void createTask(Task task,Project project)
	{
		try
		{
		
			task.setName(project.getName());
			task.setStartTime(project.getStartTime());
			task.setEndTime(project.getEndTime());
			task.setProject(project);
			task.setRate(0);
			task.setStatus(Constrains.TASK_STATUS_PROCESS);
			task.adjustNearSubmiTime();
			super.save(task);
			this.sendTaskNotice(task);
		}
		catch (Exception e)
		{
			throw new InValidException("create  task error");
		}
	}
	
	public void removeTask(Task task)
	{
		if (task.getLocked() )
			throw new InValidException("任务已被锁定,不能删除");
		if (task.getChildTasks()==null || task.getChildTasks().size()<1)
		{
			super.remove(task);
		}
		else
		{
			throw new InValidException("not remove the task because have child task");
		}
	}

	public void submitTaskAttach(Task task,TaskAttach attach,File file,String fileName)
	{
		try
		{
			if (attach==null)
			{
				attach = new TaskAttach();
			}
			attach.setTask(task);
			attach.setRate(task.getRate());
			attach.setAttach(FileUtil.getInstance().createAttach(file,fileName));
			task.addTaskAttach(attach);
			task.setLastSubmitTime(Util.nowFullTime());
			task.adjustNearSubmiTime();
			this.save(task);
			this.sendReportNotice(task);
		}
		catch (InValidException e)
		{
			throw e;
		}
		catch (Exception e)
		{
			e.printStackTrace();
			throw new InValidException("submit task'attach error");
		}
	}
	
	public 	void updateTaskAttach(TaskAttach attach,File file,String fileName)
	{
		attach.setAttach(FileUtil.getInstance().createAttach(file,fileName));
		this.getDao().saveTaskAttach(attach);
	}
	
	public void removeAttachs(Integer[] ids)
	{
		this.getDao().batchRemoveAttachs(ids);
	}


	
	public  void verifySubmit(Task task)
	{
		if (task.getAttachs()==null
				|| task.getAttachs().size()<task.getSubmitPlan())
			throw new InValidException("您提交的任务报告数量小于规定数量,不能提交");
		if (task.getChildTasks()!=null)
		{
			for (Task childtask:task.getChildTasks())
			{
				if (childtask.getStatus()!=Constrains.TASK_STATUS_END)
					throw new InValidException("有未完成的子任务或则有子任务没有通过审核");
			}
		}
	}
	



	

	/**
	 * 列出参与任务
	 */
	public PaginationSupport listJoinTask(DetachedCriteria criteria,PaginationSupport page,Person joiner)
	{
		criteria.createAlias("joiner", "j").add(Restrictions.eq("j.id", joiner.getId()));
		page.setOrders(new Order[]{Order.asc("id")});
		return super.listByPage(criteria, page);
	}
	
	public PaginationSupport listExecuteTask(DetachedCriteria criteria,PaginationSupport page,Person executor)
	{
		criteria.add(Restrictions.eq("executor", executor))
				.add(Restrictions.eq("status", Constrains.TASK_STATUS_PROCESS))
				.add(Restrictions.ne("flowstatus", Constrains.WORKFLOWENTITY_STATE_INVALID));
		page.setOrders(new Order[]{Order.asc("id")});
		return super.listByPage(criteria, page);
	}
	
	public PaginationSupport listInValidTask(DetachedCriteria criteria,PaginationSupport page,Person executor)
	{
		criteria.add(Restrictions.eq("executor", executor))
				.add(Restrictions.eq("flowstatus", Constrains.WORKFLOWENTITY_STATE_INVALID));
		page.setOrders(new Order[]{Order.asc("id")});
		return super.listByPage(criteria, page);
	} 
	
	public PaginationSupport listExecuteEndTask(PaginationSupport page,Person executor)
	{
		DetachedCriteria criteria = this.createQuery(Task.class);
		criteria.add(Restrictions.eq("executor", executor))
				.add(Restrictions.eq("status", Constrains.TASK_STATUS_END));
		page.setOrders(new Order[]{Order.asc("id")});
		return super.listByPage(criteria, page);
	}
	
	public PaginationSupport listVerifyTaskHistory(PaginationSupport page,Person verifier)
	{
		DetachedCriteria criteria =  this.createQuery(Task.class);
		criteria.add(Restrictions.eq("verifer", verifier))
				.add(Restrictions.isNotEmpty("details"));
		page.setOrders(new Order[]{Order.asc("id")});
		return super.listByPage(criteria, page);
	}
	
	public PaginationSupport listTaskReports(PaginationSupport page,Task task)
	{
		DetachedCriteria criteria = this.createQuery(TaskAttach.class);
		criteria.add(Restrictions.eq("task", task));
		page.setOrders(new Order[]{Order.asc("id")});
		return super.listByPage(criteria, page);
	}
	
	/**
	 * 创建子任务 
	 * @param childTask子任务
	 * @param rootTask
	 */
	public void createChildTask(Task childTask,Task rootTask,String joiner,File[] attachs,String[] fileNames)
	{
		if (rootTask.getLocked() )
			throw new InValidException("任务已被锁定,不能创建子任务");
		if (childTask.getEndTime()!=null &&
				childTask.getStartTime()!=null && 
				childTask.getEndTime().compareTo(childTask.getStartTime())<0)
			throw new InValidException("项目开始时间不能大于结束时间");
		if (rootTask.getStartTime()!=null)
		{
			if (childTask.getStartTime()==null)
				throw new  InValidException("开始时间不能为空");
			if (childTask.getStartTime().compareTo(rootTask.getStartTime())<0)
				throw new  InValidException("开始时间不能早于于父任务开始时间");
			if (childTask.getStartTime().compareTo(rootTask.getEndTime())>0)
				throw new  InValidException("开始时间不能晚于父任务结束时间");
		}
		if (rootTask.getEndTime()!=null)
		{
			if (childTask.getEndTime()==null)
				throw new  InValidException("结束时间不能为空");
			if (childTask.getEndTime().compareTo(rootTask.getEndTime())>0)
				throw new  InValidException("结束时间不能晚于父任务结束时间");
			if (childTask.getEndTime().compareTo(rootTask.getStartTime())<0)
				throw new  InValidException("结束时间不能早于父任务开始时间");
		}
		childTask.addAllReference(FileUtil.getInstance().createAttach(attachs, fileNames));
		Collection<Person> joiners = this.getPersonService().findPersons(ToolKits.convertStringAryToIntAry(joiner.split(",")));
		childTask.addAllJoiner(joiners);
		addChildTask(childTask,rootTask);
		super.save(childTask);
		this.sendTaskNotice(childTask);
	}
	
	
	private void addChildTask(Task task,Task parent)
	{
		try
		{
			task.setProject(parent.getProject());
			task.setRate(0);
			task.setParent(parent);
			task.setStatus(Constrains.TASK_STATUS_PROCESS);
			task.adjustNearSubmiTime();
			super.save(task);
		}
		catch (Exception e)
		{
			throw new InValidException("create  task error");
		}
	}
	
	

	
	public PaginationSupport listTaskCritique(DetachedCriteria criteria,PaginationSupport page,Task task)
	{
		criteria.add(Restrictions.eq("task", task));
		return super.listByPage(criteria, page);
	}
	
	public Task findRootTask(Project project)
	{
		return this.getDao().findRootTask(project);
	}
	
	/**
	 * 当流程结束时
	 */
	@Override
	public void onFlowEnd(Task entity)
	{
		/**
		 * 如果通过了审核，则任务执行状态为完成
		 */
		if (entity.getFlowstatus()==Constrains.WORKFLOWENTITY_STATE_VALID)
		{
			entity.setStatus(Constrains.TASK_STATUS_END);
		}
		else
		{
			entity.setRealEndTime(null);
			entity.setStatus(Constrains.TASK_STATUS_PROCESS);
		}
		super.save(entity);
	}
	
	/**
	 * 在流程开始前，验证是否可以开始流程
	 */
	@Override
	public void validateSubmit(Task entity)
	{
		if (entity.getRate()==null || entity.getRate()<100)
			throw new InValidException("任务进度不是100%,不能提交");
		if (entity.getAttachs().size()<entity.getSubmitPlan())
			throw new InValidException("没有完成所有任务报告,不能提交");
	}
	
	
	
	@Override
	public void startFlow(Task entity)
	{
		this.save(entity);
		validateSubmit(entity);
		if (entity.getParent()!=null)
			entity.setVerifer(entity.getParent().getExecutor());
		else
			entity.setVerifer(entity.getProject().getRecorder());
		entity.setRealEndTime(Util.nowFullTime());
		super.startFlow(entity);
	}
	
	public Collection<Task> findRootTasks(final Integer[] projectIds)
	{
		return this.getDao().findRootTasks(projectIds);
	}
	
	public int updateProjectTaskStatus(final Project project,final  Integer status,final Integer flowstatus)
	{
		return this.getDao().updateProjectTaskStatus(project, status, flowstatus);
	}
	
	public int executeFrostProjectTasks(Project project)
	{
		return this.getDao().updateProjectTaskStatus(project, Constrains.TASK_STATUS_FROST);
	}
	
	public int executeUnFreezeProjectTasks(Project project)
	{
		return this.getDao().updateProjectTaskStatus(project, Constrains.TASK_STATUS_PROCESS);
	}
	
	public void sendTaskNotice(Task task)
	{
		Notice notice = new Notice();
		notice.setTitle("新任务:"+task.getName());
		notice.setContent("您有一个新的项目任务:"+task.getName()+",请及时处理");
		this.getNoticeService().sendNotice(notice, task.getExecutor());
		if (task.getJoiner()!=null)
		{
			for (Person joiner : task.getJoiner())
			{
				Notice joinnotice = new Notice();
				joinnotice.setTitle("新任务:"+task.getName());
				joinnotice.setContent("您参与了一个新的项目任务:"+task.getName()+",请及时处理");
				this.getNoticeService().sendNotice(joinnotice, joiner);
			}
		}
	}
	
	/**
	 * 任务提交时，对审核人发送审核信息
	 * @param task
	 */
	private void sendVerifyNotice(Task task)
	{
		Notice notice = new Notice();
		notice.setTitle("任务:"+task.getName()+"需要审核");
		notice.setContent("任务:"+task.getName()+"需要审核,请及时处理");
		if (task.getParent()!=null)
			this.getNoticeService().sendNotice(notice, task.getParent().getExecutor());
		else
			this.getNoticeService().sendNotice(notice, task.getProject().getRecorder());
	}
	/**
	 * 当提交新报告时，给上级负责人发送通知
	 * @param task
	 * @param person
	 */
	private void sendReportNotice(Task task)
	{
		Notice notice = new Notice();
		notice.setTitle("任务:"+task.getName()+"新提交了报告");
		notice.setContent("子任务:"+task.getName()+"新提交了报告,请及时查阅");
		if (task.getParent()!=null)
			this.getNoticeService().sendNotice(notice, task.getParent().getExecutor());
		else if (task.getProject().getRecorder()!=null)
			this.getNoticeService().sendNotice(notice, task.getProject().getRecorder());
	}
	
	public Collection<Task> findExecuteTask(Person person,int result)
	{
		return this.getDao().findExecuteTask(person, result);
	}
	
	
	public int countExecuteTask(Person executor)
	{
		return this.getDao().countExecuteTask(executor);
	}
	
	public int countJoinTask(Person joiner)
	{
		return this.getDao().countJoinTask(joiner);
	}
	
	
	
	public int countVerifyTask(Person verifyer)
	{
		return this.getDao().countVerifyTask(verifyer);
	}
	
	
	public int countSumitReportTask(Person executor)
	{
		return this.getDao().countSumitReportTask(executor);
	}
	
	public int countInValidTask(Person executor)
	{
		return this.getDao().countInValidTask(executor);
	}
}
